#ifndef _DSCTBL_H
#define _DSCTBL_H 1

/**
 * 存放段描述符的结构体
 * 关于段描述符可自行百度 因为涉及保护模式 所以相关内容很多 无法一一注释
 * 个人认为暂时没必要纠结于保护模式的相关内容,而且作者也没有打算在现在就
 * 讲解过多关于保护模式的知识, 如果有兴趣的话可以参考Intel 80386手册的卷3
 * 或者赵博士的《Linux 内核完全剖析——基于0.11内核》的第四章的相关内容
 *
 * limit_low	段限长的0~15bit		base_low	段基址的0~15bit(2字节)
 * base_mid	段基址的16~23bit(1字节)	access_right(0~3bit TYPE字段, 4bit S字段 5~6 DPL字段 7bit P字段)
 * limit_high	段限长的16~19bit+AVL+D/B+G域	base_high	段基址的24~31bit(1字节)
 * - - 好吧 可能我上面关于段描述符的注释不是很清楚， 不理解的可以参考下面链接处的图片
 *http://baike.baidu.com/picview/3289301/3289301/0/0db52faddf823c3d4b36d686.html#albumindex=0&picindex=0
 */
struct SEGMENT_DESCRIPTOR {
	short limit_low, base_low;
	char base_mid, access_right;
	char limit_high, base_high;
};

/**
 *  存放门描述符的结构体
 *
 *	门描述符与段描述符类似,只是有些字段有些许差别
 *	offset_low	过程偏移地址的低16bit	selector 段选择子
 *	dw_count	参数个数, 只是调用门中有效
 *	access_right	0~3bit:TYPE字段, 4bit:S字段, 5~6bit:DPL字段, 7bit:P字段
 *	offset_high	过程偏移地址的高16bit
 */
struct GATE_DESCRIPTOR {
	short offset_low, selector;
	char dw_count, access_right;
	short offset_high;
};

/* 函数声明 */
void init_gdtidt(void);
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);

#define ADR_IDT			0x0026f800   /* IDT首地址 */
#define LIMIT_IDT		0x000007ff   /* IDT限长 */
#define ADR_GDT			0x00270000   /* GDT首地址 */
#define LIMIT_GDT		0x0000ffff   /* GDT限长 */
#define ADR_BOTPAK		0x00280000   /* 内核代码首地址 */
#define LIMIT_BOTPAK	0x0007ffff   /* 内核代码限长(共512KB) */
#define AR_DATA32_RW	0x4092       /* 32位数据段属性值 */
#define AR_CODE32_ER	0x409a       /* 32位代码段属性值 */
#define AR_INTGATE32	0x008e		 /* 32位门描述符属性值 */
#define AR_TSS32        0x0089
#define AR_LDT			0x0082       //local (segment) descriptor table

#endif
